/***************************************************
 * static的一般用法总结：
 *   面向过程：
 *       1、静态函数
 *       2、静态局部变量
 *       3、静态全局变量
 *   面向对象：
 *       1、静态成员变量
 *       2、静态成员函数
 * *************************************************/
#include<iostream>
using namespace std;

/*****************************************
 * 面向过程，静态函数：
 *   1、该函数的定义只能在本文件中使用，
 *   2、其他文件中可以定义相同名字的函数
 * **************************************/
static void func1()
{
    cout << "static.cpp  func1" << endl;
}

/******************************************************************
 * 面向过程，静态局部变量：
 *   1、该变量的生命周期不会随着函数结束而结束，而是一直存在知道程序结束
 *   2、该变量的作用域只存在于定义它的作用域范围
 * ***************************************************************/
void func2()
{
    static int val = 9;
    val++;
    cout << "static.cpp func2 val " << val << endl;
}
void func3()
{
    // cout << "static.cpp func3 val " << val << endl;  // 试图引用val，但其作用域只存在func2，此处错误
}

/******************************************************************
 * 面向过程，静态全局变量：
 *   1、该变量只在当前文件中可见，类似于静态函数
 *   2、变量初始化为0
 * ***************************************************************/
static int g_val = 0;
int g_val2 = 9;
void func4()
{
    cout << "static.cpp func4 g_val " << ++g_val << endl;
}

/**************************************************************************
 * 不管是静态成员变量还是静态成员函数，都不能在类体外加上static关键字定义，
 * 这个是因为作用域的问题，因为静态成员变量或者静态成员函数
 * 其作用域都是类，如果在外部定义时加上static，作用域就会扩大至文件域，所以会报错
 * ************************************************************************/

/******************************************************************
 * 基于对象，静态成员变量：
 *   1、静态成员变量属于某一类所有对象共享，不属于任何一个类对象
 *   2、不能在类体外加上static关键字
 * ***************************************************************/
class Base {
public:
    Base();
    ~Base();
    static int get_val();
public:
    static int val;
};
int Base::val = 10;  // 属于Base类的静态成员变量，不属于任何一个Base对象

/******************************************************************
 * 基于对象，静态成员函数：
 *   1、静态成员函数属于某一类所有对象共享，不属于任何一个类对象
 *   2、不能在类体外加上static关键字
 * ***************************************************************/
int Base::get_val()
{
    return val;
}

extern "C" void test_extern()
{
    printf("this is test extern C\n");
}